package com.bifrost.service.impl;

import com.bifrost.common.base.ServerResponse;
import com.bifrost.common.util.HttpRequestUtils;
import com.bifrost.entity.Category;
import com.bifrost.entity.Media;
import com.bifrost.entity.SapCategory;
import com.bifrost.entity.User;
import com.bifrost.exception.KnownRuntimeException;
import com.bifrost.model.CategoryModel;
import com.bifrost.repository.CategoryRepository;
import com.bifrost.repository.MediaRepository;
import com.bifrost.repository.ProductRepository;
import com.bifrost.repository.SapCategoryRepository;
import com.bifrost.service.CategoryService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author rangf
 * @date 2018/2/23
 */
@Service
@Slf4j
public class CategoryServiceImpl implements CategoryService {

    @Autowired
    CategoryRepository categoryRepository;
    @Autowired
    SapCategoryRepository sapCategoryRepository;
    @Autowired
    MediaRepository mediaRepository;
    @Autowired
    ProductRepository productRepository;
    /**
     * 通过id查询 Category
     *
     * @param categoryId
     * @return
     */
    @Override
    public Category findById(Long categoryId) {
        if (categoryId != null) {
            return categoryRepository.findOne(categoryId);
        }
        return null;
    }

    /**
     * 通过parentId 查询
     *
     * @param parentId
     * @return
     */
    @Override
    public List<Category> findByParentId(Long parentId) {
        if (parentId != null) {
            return categoryRepository.getByParentId(parentId);
        }
        return null;
    }

    /**
     * 初始化导入sapCategory
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public void sapCategoryInit() {
        List<SapCategory> sapCategoryList = sapCategoryRepository.findAll();
        if (sapCategoryList != null && !sapCategoryList.isEmpty()) {
            sapCategoryList.forEach(sapCategory -> {
                Category category = new Category();
                category.setIsArchived(Boolean.FALSE);
                category.setIsVisible(Boolean.TRUE);
                if (4 == sapCategory.getTreeLevel()) {
                    category.setParent(Boolean.FALSE);
                } else {
                    category.setParent(Boolean.TRUE);
                }
                category.setParentId(0L);
                category.setCategoryName(sapCategory.getName());
                category.setCategoryDescription(sapCategory.getDescription());
                category.setExternalId(sapCategory.getId());
                category.setCategoryCode(sapCategory.getId());
                Integer depth = sapCategory.getTreeLevel();
                category.setCategoryDepth(depth == null ? 0 : depth - 1);
                category.setCreatedTimestamp(new Date());
                category.setUpdatedTimestamp(new Date());
                categoryRepository.save(category);
            });
            sapCategoryList.forEach(sapCategory -> {
                Category category = categoryRepository.getByExternalId(sapCategory.getId());
                if (!"A".equals(sapCategory.getParent())) {
                    Category cp = categoryRepository.getByExternalId(sapCategory.getParent());
                    category.setParentId(cp.getCategoryId());
                } else {
                    category.setParentId(0L);
                }
                categoryRepository.save(category);
            });
        }
    }

    /**
     * 同步sapcategory
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public void sapCategorySync() {
        //TODO 类目同步
    }
    @Override
    //@Cacheable(value = "category:findAllCategory" )
    public List<Category> findAllCategory() {
        List categories = new ArrayList();
        List<Category> categoryList = categoryRepository.findAllByIsArchivedIsFalse(new Sort(Sort.Direction.DESC,"updatedTimestamp","createdTimestamp"));
        categoryList.stream().forEach(category -> {
            categories.add(resultCategoryMap(category));
        });

        return categories;
    }

    private List recursionCategory(Category category, List<Category> categoryList) {
        List list = new ArrayList<>();
        List<Category> categories = categoryList.stream().filter(cate -> {
            return cate.getParentId().equals(category.getCategoryId());
        }).collect(Collectors.toList());
        for (Category category1: categories){
            Map categoryMap = resultCategoryMap(category1);
            if(category1.isParent()){
                categoryMap.put("categories",recursionCategory(category1,categoryList));
                list.add(categoryMap);
            }else {
                list.add(categoryMap);
            }
        }
        return list;

    }

    @Override
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    //@CacheEvict(value = "category:findAllCategory" ,allEntries =  true)
    public void save(User user , CategoryModel categoryModel) {
        Long parentId = categoryModel.getParentId();
        Long categoryId = categoryModel.getCategoryId();
        Category category = new Category();

        /** category 不为NULL 修改分类*/
        if(categoryId !=null ){

            Category persistenceCategory = categoryRepository.findOne(categoryId);
            //Assert.isTrue(StringUtils.isNotBlank(persistenceCategory.getCategoryCode()),"不可以修改Sap数据");
            Assert.notNull(persistenceCategory,"修改的分类不存在");
            // 修改分类
            persistenceCategory = setCategory(categoryModel,persistenceCategory,user);
            Assert.notNull(categoryRepository.save(persistenceCategory),"分类修改失败");
            return;
        }else {
            // 等于NULL 新增分类
            category = setCategory(categoryModel,category,user);
        }

        String lineage="";
        // 分类级别设置
        if(parentId == null || parentId==0){
            category.setCategoryDepth(1);
            category.setParentId(0L);
        }else{
            /**不为0 查找父类 设置父类/当前类参数*/
            lineage = setParent(parentId, category);
        }
        //设置基本参数
        category.setParent(Boolean.FALSE);
        category.setCreatedTimestamp(new Date());
        Assert.notNull(category = categoryRepository.save(category),"数据保存失败");
        category.setCategoryLineage(String.format("%s%s%s",lineage,"/",category.getCategoryId()));
        log.info(String.format("分类保存成功:%s",category.toString()));

    }

    private String setParent(Long parentId, Category category) {
        String lineage;
        Category parentCate = categoryRepository.findOne(parentId);
        Assert.notNull(parentCate,"父分类不存在");
        if(!Boolean.TRUE.equals(parentCate.isParent())){
            parentCate.setParent(Boolean.TRUE);
            parentCate = categoryRepository.save(parentCate);
        }
        category.setCategoryDepth(parentCate.getCategoryDepth()+1);
        return parentCate.getCategoryLineage();
    }

    private Category setCategory(CategoryModel categoryModel, Category category , User user) {
        BeanUtils.copyProperties(categoryModel,category);

        //更新级别描述
        if(category.getCategoryId()!=null){
            String lineage="";
            if(categoryModel.getParentId().compareTo(0L)>0){
                lineage = setParent(categoryModel.getParentId(), category);
            }
            category.setCategoryLineage(String.format("%s%s%s",lineage,"/",category.getCategoryId()));
        }
        category.setMedia(mediaRepository.findFirstByHash(categoryModel.getHash()));
        category.setUpdatedBy(user.getAdminName());
        category.setUpdatedTimestamp(new Date());
        return category;
    }

    /**
     * 逻辑删除商品分类
     *
     * @param categoryId 商品分类Id
     */
    @Override
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    //@CacheEvict(value = "category:findAllCategory" , allEntries = true)
    public void delete(User user , Long categoryId) {
        Category category;
        Assert.notNull(category = categoryRepository.findOne(categoryId),"删除的分类不存在");
        Long decideCount = categoryRepository.countAllIsArchivedByparent(categoryId,false);
        if(decideCount.compareTo(0L)>0){
            throw new IllegalArgumentException("不能直接删除父分类");
        }
        // 得到分类下商品未归档的数量 判断该分类是否可以归档
        decideCount =  productRepository.countAllByIsArchivedByCate(categoryId,false);
        if(decideCount.compareTo(0L)>0){
            throw new IllegalArgumentException("请先删除分类下的商品");
        }
        category.setUpdatedBy(user.getAdminName());
        category.setIsArchived(Boolean.TRUE);
        category = categoryRepository.save(category);

        // 如果所有子分类都归档 更改父分类的isParent
        decideCount = categoryRepository.countAllIsArchivedByparent(category.getParentId(),false);
        if(decideCount.compareTo(1L)<1){
            Category parentCategory = categoryRepository.findOne(category.getParentId());
            parentCategory.setParent(Boolean.FALSE);
        }
        log.info(String.format("分类删除成功:%s", category.toString()));
    }

    @Override
    public Category findOne(Long parentId) {
        if (parentId!=null){
            return categoryRepository.findOne(parentId);
        }
        return null;
    }

    @Override
    public CategoryModel detail(Long categoryId) {

        Category category = categoryRepository.findOne(categoryId);
        Assert.notNull(category,"当前分类不存在");
        CategoryModel categoryModel = new CategoryModel();
        BeanUtils.copyProperties(category,categoryModel);
        Media media = category.getMedia();
        categoryModel.setCategoryImg(media==null?null:HttpRequestUtils.getUrl(media.getUrl()));
        categoryModel.setHash(media==null?null:media.getHash());

        return categoryModel;
    }


    public Map resultCategoryMap(Category category){
        Map categoryMap = new HashMap<>();
        if(category!=null) {
            categoryMap.put("categoryId", category.getCategoryId());
            categoryMap.put("categoryName", category.getCategoryName());
            categoryMap.put("externalId", category.getExternalId());
            categoryMap.put("isParent", category.isParent());
            categoryMap.put("isVisible", category.getIsVisible());
            categoryMap.put("isArchived", category.getIsArchived());
            categoryMap.put("description", category.getCategoryDescription());
            Media media = category.getMedia();
            categoryMap.put("url", media==null?null:HttpRequestUtils.getUrl(media.getUrl()));
            //categoryMap.put("sortOrder", category.getSortOrder());
            categoryMap.put("parentId", category.getParentId()==null?0:category.getParentId());
        }
        categoryMap.put("categories",null);
        return categoryMap;
    }
}

